package erfgame.core.world.terrain.rotated;

import java.awt.Dimension;
import java.awt.Point;

import erfgame.core.PointTransformation;
import erfgame.core.Rotation;

public class TransformedBlock<PartType> {
	private PartType[][] block;
	private int width;
	private int height;
	private PointTransformation transformation; 
	private Point tempPoint = new Point();
	private int originalWidth;
	private int originalHeight;
	private Rotation rotation;
	
	public TransformedBlock( PartType[][] block, int width, int height ) 
	{
		this.block = block;
		this.originalWidth = width;
		this.originalHeight = height;		
	}
	
	public TransformedBlock( 
			PartType[][] block, 
			Rotation rotation, 
			PointTransformation transformation,
			int width, 
			int height
	){
		this( block, width, height );
		this.setRotation( rotation, transformation );
	}
	
	public PointTransformation getTransformation() {
		return this.transformation;
	}
	
	public void setTransformation( PointTransformation transformation ) {
		this.transformation = transformation;
	}
	
	public void setRotation( Rotation rotation, PointTransformation transformation ) {
		Dimension dimension = new Dimension();
		this.rotation = rotation;
		rotation.rotate( originalWidth, originalHeight, dimension );
		this.width = dimension.width;
		this.height = dimension.height;
		setTransformation( transformation );
	}
	
	public Rotation getRotation() {
		return this.rotation;
	}
	
	public PartType getPart( int x, int y ) {
		return getPart( x, y, tempPoint );
	}
	
	public PartType getPart( int x, int y, Point tempPoint ) {
		Point p = getRotatedPoint( x, y, tempPoint );
//		if( p.x >= width || p.y >= height ) {
//			throw new RuntimeException( "("+p.x+","+p.y+") > ("+width+","+height+")" );
//		}
		return block[p.x][p.y];
	}
	
	public Point getRotatedPoint( int x, int y ) {
		return getRotatedPoint( x, y, tempPoint );
	}
	
	public Point getRotatedPoint( int x, int y, Point tempPoint ) {
		//return rotation.rotate(x, y, midPointTimes2, tempPoint);
		//return rotation.rotateInBox(x, y, midPointTimes2.x, midPointTimes2.y, tempPoint );
		transformation.transform(x, y, tempPoint);
		return tempPoint;
	}
	
	public boolean isRotatedPointValid( Point p ) {
		return p.x >= 0 && p.y >= 0 && p.x < originalWidth && p.y < originalWidth;
	}
	
	public PartType[][] getRawData() {
		return this.block;
	}
	
	public void setPart( int x, int y, PartType part ) {
		setPart( x, y, part, tempPoint );
	}
	
	public void setPart( int x, int y, PartType part, Point tempPoint ){
		//Point p = rotation.rotate(x, y, midPointTimes2, tempPoint );
		//Point p = rotation.rotateInBox(x, y, midPointTimes2.x, midPointTimes2.y, tempPoint );
		transformation.transform(x, y, tempPoint);
		block[tempPoint.x][tempPoint.y] = part;
	}
	
	public int getWidth() {
		return this.width;
	}
	
	public int getHeight() {
		return this.height;
	}
}
